﻿using System;
using wbServo.cache;
using wbServo.dao;
using wbServo.domain;
using wbServo.entity;

namespace wbServo.service
{
    public class FuncService
    {
        private readonly object _lock = new object();
        public ResultData_FUNC ExecFunction(string funcName, string param)
        {
            //初始化过程相关的参数
            ResultData_FUNC result = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success"
            };

            LogEntity logEntity = new LogEntity
            {
                WORK_NAME = "[流程-事件触发]-PLC",
                WORK_PROC = "FuncService.ExecFunction",
                WORK_CODE = "0",
                WORK_MSG = "success",
                CONT_NO = "",
                WORK_SEC = 1,
                CREATOR = 1001,
                CREATOR_NAME = "WCS",
                CREATE_DATE = DateTime.Now
            };

            if (!GlobalCachePool.single_plcItem_dict.TryGetValue(param, out PlcItemEntity item))
            {
                result.Code = "404";
                result.Msg = $"信号点[{param}]未在[PLC_ITEM]表中配置!]";
                return result;
            }

            if ("CREATE_TASK".Equals(funcName))
            {
                logEntity.WORK_NAME = "[流程-任务创建]-PLC";
                //收到信息解析后创建任务
                lock (_lock)
                {
                    result = CreateTask(item.UNIT_NO, item.ITEM_VALUE);
                }
                //将确认信号的itemNo匹配出来
                string itemConfirm = item.ITEM_NO.Replace("PLC_D6900", "AGV_D6905");
                result.Writes = result.Writes + itemConfirm + "=" + item.ITEM_VALUE;
            }
            else if ("CANCEL_TASK".Equals(funcName))
            {
                logEntity.WORK_NAME = "[流程-任务取消]-PLC";
                //修改为精准匹配任务链
                lock (_lock)
                {
                    result = CancelTask(item.UNIT_NO, item.ITEM_VALUE);
                }
                //将确认信号的itemNo匹配出来
                string itemCancel = item.ITEM_NO.Replace("PLC_D6910", "AGV_D6915");
                result.Writes = result.Writes + itemCancel + "=" + item.ITEM_VALUE;
            }
            else
            {
                result.Code = "404";
                result.Msg = $"未匹配到相关方法{funcName}";
            }
            //记录日志
            logEntity.CONT_NO = param;
            logEntity.WORK_CODE = result.Code;
            logEntity.WORK_MSG = result.Msg;
            DBFactory.Insert2WorkLog(logEntity);

            //根据传入的参数获取对应的站台编号
            return result;
        }

        private ResultData_FUNC CreateTask(string unitNo, string taskCode)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success",
                Writes = ""
            };

            try
            {
                //检查一下routeSet中是否配置任务链(根据unitNo+taskCode匹配唯一)
                string routeSql = $"select * from wcs_route_set where unit_no='{unitNo}' and carry_no='{taskCode}' limit 1";
                //资料编号
                string contType = "404";
                RouteSetEntity routePath = DBFactory.QueryFirst<RouteSetEntity>(routeSql);
                if (routePath == null)
                {
                    resultData.Code = "create_task_error_01";
                    resultData.Msg = $"设备[{unitNo}]任务链[{taskCode}]未在wcs_route_set中配置!请核查!";
                    return resultData;
                }

                //获取当前站点的资料编号
                if (GlobalCachePool.single_plcItem_dict.TryGetValue(routePath.NEXT_POS, out PlcItemEntity item))
                {
                    contType = item.ITEM_VALUE;
                }

                //检查一下当前是否有该任务链的任务正在执行
                string trkSql = $"select * from wcs_trk where unit_no='{unitNo}' and cont_no='{taskCode}' and trk_st <2 limit 1";
                TrkEntity trk = DBFactory.QueryFirst<TrkEntity>(trkSql);
                if (trk != null)
                {
                    resultData.Code = "create_task_error_01";
                    resultData.Msg = $"任务链[{taskCode}]存在执行中的任务ID[{trk.TRK_ID}],请稍后请求!";
                    return resultData;
                }

                //生成wcs_trk即可
                TrkEntity wcsTrk = new TrkEntity
                {
                    REQUEST_PK = DateTime.Now.ToString("yyyyMMddHHmmss"),
                    CONT_NO = taskCode,
                    DVC_NO = routePath.DVC_NO,
                    UNIT_NO = routePath.UNIT_NO,
                    CONT_TYPE = contType,
                    TRK_TYPE = routePath.TRK_TYPE,
                    //下料的优先级高
                    TRK_PRTY = "1",
                    FRM_POS = routePath.FRM_POS,
                    TO_POS = routePath.TO_POS,
                    CUR_POS = routePath.CUR_POS,
                    IS_FULL = "1",
                    GROUP_NO = "",
                    CREATOR = 1001,
                    CREATE_DATE = DateTime.Now
                };

                DBFactory.Insert2WcsTrk(wcsTrk);
                //任务创建成功需要给PLC确认信号(将任务链写给PLC,从6200地址开始)
                string plcSql = $"select * from plc_item where unit_no='{unitNo}' and item_value='0' and item_grp like 'TASK%' order by item_adr limit 1";
                PlcItemEntity plcItem = DBFactory.QueryFirst<PlcItemEntity>(plcSql);
                if (plcItem != null)
                {
                    resultData.Writes = plcItem.ITEM_NO + "=" + taskCode + ";";
                }
                resultData.Msg = $"设备[{unitNo}]创建任务链[{taskCode}]搬送任务成功!";
                return resultData;
            }
            catch (Exception ex)
            {
                resultData.Code = "create_task_error_500";
                resultData.Msg = $"设备[{unitNo}]创建任务{taskCode}链搬送任务失败!causeBy:{ex.Message}";
                return resultData;
            }
        }

        /// <summary>
        /// 精准取消任务链
        /// </summary>
        /// <param name="liftNo"></param>
        /// <returns></returns>
        private ResultData_FUNC CancelTask(string unitNo, string taskCode)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success",
                Writes = ""
            };

            try
            {
                //判断一下WCS中是否存在可取消的任务
                string trkSql = $"select * from wcs_trk where unit_no='{unitNo}' and cont_no = '{taskCode}' and trk_st <2 limit 1";
                TrkEntity trk = DBFactory.QueryFirst<TrkEntity>(trkSql);
                if (trk == null)
                {
                    resultData.Code = "cancel_task_error_01";
                    resultData.Msg = $"设备[{unitNo}]不存在任务链[{taskCode}]的搬送任务,无需取消!";
                    return resultData;
                }
                //存在任务直接取消即可（同时取消对应的AGV搬送任务）
                trk.TRK_ST = 4;
                trk.UPDATE_DATE = DateTime.Now;
                trk.COMMENTS = $"派单系统对任务链{taskCode}的搬送任务进行取消操作!";
                DBFactory.UpdateTrkById(trk);
                //取消AGV相关任务
                string agvSql = $"select * from agv_trk_hk where trk_id={trk.TRK_ID} limit 1";
                AgvTrkEntity agvTrk = DBFactory.QueryFirst<AgvTrkEntity>(agvSql);
                if (agvTrk != null)
                {
                    agvTrk.STATUS = 40;
                    agvTrk.DATA = $"派单系统对任务链{taskCode}的搬送任务进行取消操作!";
                    //更新AGV任务的状态40
                    DBFactory.UpdateAgvTrkById(agvTrk);
                    resultData.Msg = $"同时取消AGV搬送任务[{agvTrk.TASK_CODE}]!";
                }
                //找到匹配的任务链并清空
                string plcSql = $"select * from plc_item where unit_no='{unitNo}' and item_value='{trk.CONT_NO}' and item_grp like 'TASK%' limit 1";
                PlcItemEntity plcItem = DBFactory.QueryFirst<PlcItemEntity>(plcSql);
                if (plcItem != null)
                {
                    resultData.Writes = plcItem.ITEM_NO + "=0;";
                }
                resultData.Msg = $"派单系统取消设备[{unitNo}]的任务链[{taskCode}]成功!" + resultData.Msg;
            }
            catch (Exception ex)
            {
                resultData.Code = "cancel_task_error_500";
                resultData.Msg = $"派单系统取消设备[{unitNo}]的任务链{taskCode}失败!causeBy:{ex.StackTrace}";
                return resultData;
            }

            return resultData;
        }
    }
}
